﻿using FlyIL.Misc;
using FlyIL.Optimizer;
using System.Linq;

namespace FlyIL.Advance
{
    public static class ContextEx
    {
        private static readonly SimplfyRoot root = new();

        #region  旧代码 


        //public static void CheckSimpfy(this Context self, IReader reader, Inst last)
        //{

        //    self.CheckCondition(reader);
        //    self.CheckIndex(reader);


        //    if (last == null)
        //        return;

        //    var inst = last.Value;

        //    if (inst.Opt == Opt.jmp && inst.O1.IsRegister)
        //    {
        //        self.CheckJmpXxx(reader, last);
        //    }
        //    else if (inst.Opt == Opt.ret)
        //    {
        //        self.CheckRetXxx(reader, last);
        //    }

        //}

        //// 检测 mov R5D, dword ptr[Esp + R6D * 2 + 0xB905BA8C]
        //// 能否化简为  纯栈内变量  [Esp + xxx]
        //// 方便后续的分析和化简 

        //public static void CheckIndex(this Context self, IReader reader)
        //{
        //    var inst = self.Last.Value;


        //    bool left = inst.O1.Index != RegCode.None;
        //    bool right = inst.O2.Index != RegCode.None;

        //    if (!left && !right)
        //        return;

        //    Operand op;
        //    if (left)
        //        op = new Operand { Base = inst.O1.Index };
        //    else
        //        op = new Operand { Base = inst.O2.Index };


        //    if (inst.Vip == 0x426BE24)
        //        ;

        //    var nnn = Tracer.TraceUp(self, self.Last.Previous, op);
        //    if (nnn == null)
        //        return;

        //    Cpu cpu = new Cpu(self.Is64, null);
        //    cpu.Reader = reader;


        //    /// 最后一条指令 不执行 
        //    cpu.Run(self, nnn, self.Codes.Last);


        //    ulong val = cpu.Context[op.Base];

        //    if (left)
        //    {
        //        inst.O1.Index = RegCode.None;
        //        inst.O1.u32 = (uint)(val * inst.O1.Scale) + inst.O1.u32;
        //    }
        //    else
        //    {
        //        inst.O2.Index = RegCode.None;
        //        inst.O2.u32 = (uint)(val * inst.O2.Scale) + inst.O2.u32;
        //    }
        //    //Dump();


        //}



        ///// <summary>
        ///// 检测 语句的条件是否确定 , 不只 jcc 语句 
        ///// </summary>
        //public static void CheckCondition(this Context self, IReader reader)
        //{
        //    var inst = self.Last.Value;

        //    if (inst.ExpCon == null)
        //        return;


        //    var exp = Tracer.TraceExp(self, self.Last, inst.ExpCon);

        //    if (exp != null && exp.Calculable)
        //    {

        //        if (exp.Result > 0)
        //            inst.ExpCon = null;
        //        else
        //            inst.Opt = Opt.nop;

        //    }

        //}


        ///// <summary>
        ///// 形如  jmp eax , 或者  jmp dword ptr [esi + ?? ] 
        ///// </summary>
        ///// <param name="reader"></param>
        ///// <param name="node"></param>
        //public static void CheckJmpXxx(this Context self, IReader reader, Inst node)
        //{
        //    var inst = self.Last.Value;

        //    if (inst.Opt != Opt.jmp)
        //        return;
        //    if (inst.O1.IsImm)
        //        return;

        //    var exp = Tracer.TraceStrict(self, self.Last, ref inst.O1);

        //    if (exp != null && exp.IsValid == true && exp.Calculable)
        //    {
        //        if (self.Is64)
        //            self.Last.jmp(exp.Result);
        //        else
        //            self.Last.jmp((uint)exp.Result);
        //    }


        //}


        ///// <summary>
        ///// 检查是否伪装成 jmp的 ret
        ///// </summary>
        ///// <param name="reader"></param>
        ///// <param name="node"></param>
        //public static void CheckRetXxx(this Context self, IReader reader, Inst node)
        //{

        //    if (node.Opt != Opt.ret)
        //        return;

        //    var pre = self.GetPreviousIfExist(node);

        //    var op = (self.Is64) ? _qword_[AssemblerRegisters.Rsp] : _dword_[AssemblerRegisters.Esp];
        //    var nnn = Tracer.TraceWeak(self, pre, ref op);

        //    if (nnn != null && nnn.IsValid)
        //    {
        //        if (nnn.Calculable)
        //        {

        //            byte index = node.O1.u8;
        //            if ((self.Is64))
        //            {
        //                node.lea(AssemblerRegisters.Rsp, (ExprRegister.Rsp + (ulong)index));
        //                self.Make(node.Vip, 1).jmp(nnn.Result);
        //            }
        //            else
        //            {
        //                node.lea(AssemblerRegisters.Esp, (ExprRegister.Esp + (ulong)index));
        //                self.Make(node.Vip, 1).jmp((uint)nnn.Result);

        //            }
        //        }
        //    }
        //}



        ///// <summary>
        ///// 对可以确定的 赋值语句，直接计算并用结果来代替
        ///// 可以为后面的 Trace 减轻工作量
        ///// 同时也是后面 化简的基础 
        ///// </summary>
        //public static void CheckAssignment(this Context self, IReader reader, Inst node = null)
        //{
        //    if (node == null)
        //        node = self.Codes.Last;

        //    if (node.Opt.IsForgetTruncation())
        //    {
        //        var inst = node.Value;


        //        if (inst.Opt == Opt.pop)
        //        {
        //            Operand op = new OperandMaker(inst.O1.BitSize / 8)[self.RegSp];


        //            var nnn = Tracer.TraceUp(self, node.Previous, op);

        //            if (nnn != null)
        //            {
        //                Cpu cpu = new Cpu(self.Is64, reader);

        //                cpu.Run(self, nnn, node);

        //                if (inst.O1.BitSize == 32)
        //                {
        //                    node.mov(inst.O1, cpu.Stacks32.Vsp_0);
        //                    self.Make(inst.Vip, inst.SubIp + 1).lea(self.RegSp, self.RegSpExp + (ulong)(inst.O1.BitSize / 8));

        //                }
        //            }

        //        }
        //    }

        //    ;


        //}



        #endregion




        /// <summary>
        /// 仅对一条指令 进行化简 
        /// </summary>
        public static void SimplifyOnce(this Context self, Inst node = null)
        {
            node ??= self.Last;

            root.GetSubMatch(self, node)?.Do(self, node);

          //  self?.DumpFlow();
        }


        /// <summary>
        /// 对 *同一ip的* 一组指令   执行化简  
        /// 这里是 化简的 正常入口
        /// </summary>
        public static void SimplifyGroup(this Context self, Inst last = null)
        {
            last ??= self.Last;
            //if (last.Vip == 0x0000000002f9e8da)
            //    ;

            Inst c = last;
            while (c.SubIp != 0)
                c = c.Previous;


            ulong lastip = last.Vip;

            for (; c != null && c.Vip == lastip; c = self.GetNextIfExist(c))
            {
                root.GetSubMatch(self, c)?.Do(self, c);
               // self?.DumpFlow();

            }

            //self?.DumpFlow();

            ;


        }

        /// <summary>
        /// 在两个节点之间 进行化简 ，出现分支则退出 
        /// </summary>
        public static void SimplifyBetween(this Context self, Inst start = null, Inst stop = null)
        {

            start ??= self.Entry;

            var node = self.GetNextIfExist(start);
            /// rep 相当于 一个独立的单元 
            bool repfound = false;

            /// 自前 向后遍历 
            for (; node != null && node != stop; node = self.GetNextIfExist(node))
            {

                if (node.HavePrefix)
                    repfound = true;
                else if (node.EndPrefix)
                    repfound = false;


                if (repfound)
                    continue;

                //if (node.Vip == 0x0000000003037ab9)
                //    ;

                root.GetSubMatch(self, node)?.Do(self, node);

#if DEBUG
               // self.DumpFlow(node);
#endif
                ;

            }
        }




        public static void NopFlow(this Context self, Inst start, Inst stop, params Opt[] opts)
        {

            var node = self.GetNextIfExist(start);
            /// rep 相当于 一个独立的单元 
            bool repfound = false;

            /// 自前 向后遍历 
            for (; node != null && node != stop; node = self.GetNextIfExist(node))
            {

                if (node.HavePrefix)
                    repfound = true;
                else if (node.EndPrefix)
                    repfound = false;


                if (repfound)
                    continue;

                if (opts.Contains(node.Opt))
                    self.NOP(node);

            }

        }




    }




}
